/**
 * 
 */
package com.mc.wordpdf;

// 测试 00
//import java.io.File;  
//import java.io.FileInputStream;  
//import java.io.FileOutputStream;  
//import java.io.IOException;  
//import java.io.InputStream;  
//import java.util.ArrayList;  
//import java.util.List;
//import java.util.UUID;
//
//import com.alibaba.fastjson.JSON;
//import com.itextpdf.text.BaseColor;  
//import com.itextpdf.text.Element;  
//import com.itextpdf.text.Image;  
//import com.itextpdf.text.Rectangle;  
//import com.itextpdf.text.pdf.AcroFields;  
//import com.itextpdf.text.pdf.BaseFont;  
//import com.itextpdf.text.pdf.PdfContentByte;  
//import com.itextpdf.text.pdf.PdfDictionary;  
//import com.itextpdf.text.pdf.PdfName;  
//import com.itextpdf.text.pdf.PdfReader;  
//import com.itextpdf.text.pdf.PdfStamper;  
//import com.itextpdf.text.pdf.parser.ContentByteUtils;  
//import com.itextpdf.text.pdf.parser.ImageRenderInfo;  
//import com.itextpdf.text.pdf.parser.PdfContentStreamProcessor;  
//import com.itextpdf.text.pdf.parser.RenderListener;  
//import com.itextpdf.text.pdf.parser.TextRenderInfo;
//import com.mc.parameter.Parameter;  

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;

import com.itextpdf.text.pdf.parser.*;
import com.itextpdf.text.pdf.PdfDictionary;
import com.itextpdf.text.pdf.PdfName;
import com.itextpdf.text.pdf.PdfReader;
import com.mc.parameter.Parameter; 

/**
 * @author w.weizhen
 *
 */
public class ItextpdfTest {
	
	// 当前模块,数据和文件存放路径
	private static final String path = Parameter.data_path + "poitl" + File.separator;
	private static final String pdfName = "fxcjcbl_template89.pdf";
	private static final String imgName = "0010.png";
	private static final String keyword = "签名";
	private static final String new_pdf = path + UUID.randomUUID().toString().replaceAll("-", "") + ".pdf";
	
	
	public static void main(String[] args) throws IOException {
        //1.给定文件
        File pdfFile = new File(path + pdfName);
        //2.定义一个byte数组，长度为文件的长度
        byte[] pdfData = new byte[(int) pdfFile.length()];

        //3.IO流读取文件内容到byte数组
        FileInputStream inputStream = null;
        try {
            inputStream = new FileInputStream(pdfFile);
            inputStream.read(pdfData);
        } catch (IOException e) {
            throw e;
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                }
            }
        }

        //4.指定关键字
        //keyword

        //5.调用方法，给定关键字和文件
        List<float[]> positions = findKeywordPostions(pdfData, keyword);

        //6.返回值类型是  List<float[]> 每个list元素代表一个匹配的位置，分别为 float[0]所在页码  float[1]所在x轴 float[2]所在y轴
        System.out.println("total:" + positions.size());
        if (positions != null && positions.size() > 0) {
            for (float[] position : positions) {
                System.out.print("pageNum: " + (int) position[0]);
                System.out.print("\tx: " + position[1]);
                System.out.println("\ty: " + position[2]);
                
                pdfboxDrawImage(position[1], position[2]);
                
            }
        }
    }


    /**
     * findKeywordPostions
     * @param pdfData     通过IO流 PDF文件转化的byte数组
     * @param keyword     关键字
     * @return List<float [ ]> : float[0]:pageNum float[1]:x float[2]:y
     * @throws IOException
     */
    public static List<float[]> findKeywordPostions(byte[] pdfData, String keyword) throws IOException {
        List<float[]> result = new ArrayList<>();
        List<PdfPageContentPositions> pdfPageContentPositions = getPdfContentPostionsList(pdfData);


        for (PdfPageContentPositions pdfPageContentPosition : pdfPageContentPositions) {
            List<float[]> charPositions = findPositions(keyword, pdfPageContentPosition);
            if (charPositions == null || charPositions.size() < 1) {
                continue;
            }
            result.addAll(charPositions);
        }
        return result;
    }


    private static List<PdfPageContentPositions> getPdfContentPostionsList(byte[] pdfData) throws IOException {
        PdfReader reader = new PdfReader(pdfData);


        List<PdfPageContentPositions> result = new ArrayList<>();


        int pages = reader.getNumberOfPages();
        for (int pageNum = 1; pageNum <= pages; pageNum++) {
            float width = reader.getPageSize(pageNum).getWidth();
            float height = reader.getPageSize(pageNum).getHeight();

            PdfRenderListener pdfRenderListener = new PdfRenderListener(pageNum, width, height);

            //解析pdf，定位位置
            PdfContentStreamProcessor processor = new PdfContentStreamProcessor(pdfRenderListener);
            PdfDictionary pageDic = reader.getPageN(pageNum);
            PdfDictionary resourcesDic = pageDic.getAsDict(PdfName.RESOURCES);
            try {
                processor.processContent(ContentByteUtils.getContentBytesForPage(reader, pageNum), resourcesDic);
            } catch (IOException e) {
                reader.close();
                throw e;
            }


            String content = pdfRenderListener.getContent();
            List<CharPosition> charPositions = pdfRenderListener.getcharPositions();


            List<float[]> positionsList = new ArrayList<>();
            for (CharPosition charPosition : charPositions) {
                float[] positions = new float[]{charPosition.getPageNum(), charPosition.getX(), charPosition.getY()};
                positionsList.add(positions);
            }


            PdfPageContentPositions pdfPageContentPositions = new PdfPageContentPositions();
            pdfPageContentPositions.setContent(content);
            pdfPageContentPositions.setPostions(positionsList);


            result.add(pdfPageContentPositions);
        }
        reader.close();
        return result;
    }


    private static List<float[]> findPositions(String keyword, PdfPageContentPositions pdfPageContentPositions) {


        List<float[]> result = new ArrayList<>();


        String content = pdfPageContentPositions.getContent();
        List<float[]> charPositions = pdfPageContentPositions.getPositions();


        for (int pos = 0; pos < content.length(); ) {
            int positionIndex = content.indexOf(keyword, pos);
            if (positionIndex == -1) {
                break;
            }
            float[] postions = charPositions.get(positionIndex);
            result.add(postions);
            pos = positionIndex + 1;
        }
        return result;
    }


    private static class PdfPageContentPositions {
        private String content;
        private List<float[]> positions;


        public String getContent() {
            return content;
        }


        public void setContent(String content) {
            this.content = content;
        }


        public List<float[]> getPositions() {
            return positions;
        }


        public void setPostions(List<float[]> positions) {
            this.positions = positions;
        }
    }

    private static class PdfRenderListener implements RenderListener {
        private int pageNum;
        private float pageWidth;
        private float pageHeight;
        private StringBuilder contentBuilder = new StringBuilder();
        private List<CharPosition> charPositions = new ArrayList<>();

        public PdfRenderListener(int pageNum, float pageWidth, float pageHeight) {
            this.pageNum = pageNum;
            this.pageWidth = pageWidth;
            this.pageHeight = pageHeight;
        }

        public void beginTextBlock() {
        }

        public void renderText(TextRenderInfo renderInfo) {
            List<TextRenderInfo> characterRenderInfos = renderInfo.getCharacterRenderInfos();
            for (TextRenderInfo textRenderInfo : characterRenderInfos) {
                String word = textRenderInfo.getText();
                if (word.length() > 1) {
                    word = word.substring(word.length() - 1, word.length());
                }
                com.itextpdf.awt.geom.Rectangle2D.Float rectangle = textRenderInfo.getAscentLine().getBoundingRectange();

                float x = (float)rectangle.getX();
                float y = (float)rectangle.getY();
//                float x = (float)rectangle.getCenterX();
//                float y = (float)rectangle.getCenterY();
//                double x = rectangle.getMinX();
//                double y = rectangle.getMaxY();

                //这两个是关键字在所在页面的XY轴的百分比
                float xPercent = Math.round(x / pageWidth * 10000) / 10000f;
                float yPercent = Math.round((1 - y / pageHeight) * 10000) / 10000f;

//                CharPosition charPosition = new CharPosition(pageNum, xPercent, yPercent);
                CharPosition charPosition = new CharPosition(pageNum, (float)x, (float)y);
                charPositions.add(charPosition);
                contentBuilder.append(word);
            }
        }

        public void endTextBlock() {
        }

        public void renderImage(ImageRenderInfo renderInfo) {
        }

        public String getContent() {
            return contentBuilder.toString();
        }

        public List<CharPosition> getcharPositions() {
            return charPositions;
        }
    }

    private static class CharPosition {
        private int pageNum = 0;
        private float x = 0;
        private float y = 0;

        public CharPosition(int pageNum, float x, float y) {
            this.pageNum = pageNum;
            this.x = x;
            this.y = y;
        }

        public int getPageNum() {
            return pageNum;
        }

        public float getX() {
            return x;
        }
        
        public float getY() {
            return y;
        }
        
        @Override
        public String toString() {
            return "[pageNum=" + this.pageNum + ",x=" + this.x + ",y=" + this.y + "]";
        }
    }
	
    
    /**
	 * org.apache.pdfbox 实现在指定位置插入图片
	 * 问题难点:不能确定准确位置
	 */
	private static void pdfboxDrawImage(float offset_x, float offset_y)
	{
		try {
			File file = new File(path + pdfName);
	        PDDocument doc = PDDocument.load(file);
	        PDPage myPage = doc.getPage(0);
	        PDImageXObject pdImage = PDImageXObject.createFromFile(path + imgName, doc);
	        
	        //计算长宽,避免图片过大
	        BigDecimal max_width = BigDecimal.valueOf(50);
            BigDecimal width = BigDecimal.valueOf(pdImage.getWidth());
            BigDecimal height = BigDecimal.valueOf(pdImage.getHeight());
            BigDecimal ratio = width.divide(max_width, 3, BigDecimal.ROUND_UP);
            
            width = max_width;
            height = height.divide(ratio, 3, BigDecimal.ROUND_UP);
            
            //位置
	        offset_x = offset_x + 60;
	        offset_y = offset_y - 20;
            
	        try (PDPageContentStream cont = new PDPageContentStream(doc, myPage, PDPageContentStream.AppendMode.APPEND, false, false)) {
	            cont.drawImage(pdImage, offset_x, offset_y, width.intValue(), height.intValue());
	        }
	        String new_pdf = path + UUID.randomUUID().toString().replaceAll("-", "") + ".pdf";
	        doc.save(new_pdf);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
    
    
    
	
//    测试 00
//	/**
//	 * @param args
//	 * @throws Exception
//	 */
//	public static void main(String[] args) throws Exception {
//		File pdfFile = new File(path + pdfName);
//		byte[] pdfData = new byte[(int) pdfFile.length()];
//		FileInputStream inputStream = null;
//		try {
//			inputStream = new FileInputStream(pdfFile);
//			inputStream.read(pdfData);
//		} catch (IOException e) {
//			throw e;
//		} finally {
//			if (inputStream != null) {
//				try {
//					inputStream.close();
//				} catch (IOException e) {
//				}
//			}
//		}
//
//		List<float[]> positions = findKeywordPostions(pdfData, keyword);
//
//		System.out.println("total:" + positions.size());
//		if (positions != null && positions.size() > 0) {
//			System.out.print(JSON.toJSONString(positions));
//			for (float[] position : positions) {
//				System.out.print("pageNum: " + (int) position[0]);
//				System.out.print("\tx: " + position[1]);
//				System.out.println("\ty: " + position[2]);
//				gaizhang(pdfFile, new File(new_pdf), (int) position[0], position[1], position[2], path + imgName);
//			}
//		}
//	}
//
//	public static void gaizhang(File src, File dest, int page, float x, float y, String imagePath) throws Exception {
//		// 读取模板文件
//		InputStream input = new FileInputStream(src);
//		PdfReader reader = new PdfReader(input);
//		PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
//		Rectangle pageSize = reader.getPageSize(1);
////    float height = pageSize.getHeight();  
////    float width = pageSize.getWidth();  
////    x = width*x;  
////    y = height-height*y-145;
//
//		x = x * 1000;
//		y = y * 1000;
//
//		// 读图片
//		Image image = Image.getInstance(imagePath);
//		// 获取操作的页面
//		PdfContentByte under = stamper.getOverContent(page);
//		// 添加图片
//		// 图像在本页的相对位置
//		image.setAbsolutePosition(x, y);
//		// 图片的缩放大小
//		image.scalePercent(10, 10);
//		under.addImage(image);
//
//		stamper.close();
//		reader.close();
//	}
//
//	/**
//	 * 
//	 * 【功能描述：添加图片和文字水印】 【功能详细描述：功能详细描述】
//	 * 
//	 * @param srcFile    待加水印文件
//	 * @param destFile   加水印后存放地址
//	 * @param text       加水印的文本内容
//	 * @param textWidth  文字横坐标
//	 * @param textHeight 文字纵坐标
//	 * @throws Exception
//	 */
//	public void addWaterMark(String srcFile, String destFile, String text, int textWidth, int textHeight)
//			throws Exception {
//		// 待加水印的文件
//		PdfReader reader = new PdfReader(srcFile);
//		// 加完水印的文件
//		PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(destFile));
//		int total = reader.getNumberOfPages() + 1;
//		PdfContentByte content;
//		// 设置字体
//		BaseFont font = BaseFont.createFont();
//		// 循环对每页插入水印
//		for (int i = 1; i < total; i++) {
//			// 水印的起始
//			content = stamper.getUnderContent(i);
//			// 开始
//			content.beginText();
//			// 设置颜色 默认为蓝色
//			content.setColorFill(BaseColor.BLUE);
//			// content.setColorFill(Color.GRAY);
//			// 设置字体及字号
//			content.setFontAndSize(font, 38);
//			// 设置起始位置
//			// content.setTextMatrix(400, 880);
//			content.setTextMatrix(textWidth, textHeight);
//			// 开始写入水印
//			content.showTextAligned(Element.ALIGN_LEFT, text, textWidth, textHeight, 45);
//			content.endText();
//		}
//		stamper.close();
//	}
//
//	/**
//	 * findKeywordPostions
//	 * 
//	 * @param pdfData
//	 * @param keyword
//	 * @return List<float[]> : float[0]:pageNum float[1]:x float[2]:y
//	 * @throws IOException
//	 */
//	public static List<float[]> findKeywordPostions(byte[] pdfData, String keyword) throws IOException {
//		List<float[]> result = new ArrayList<float[]>();
//		List<PdfPageContentPositions> pdfPageContentPositions = getPdfContentPostionsList(pdfData);
//
//		for (PdfPageContentPositions pdfPageContentPosition : pdfPageContentPositions) {
//			List<float[]> charPositions = findPositions(keyword, pdfPageContentPosition);
//			if (charPositions == null || charPositions.size() < 1) {
//				continue;
//			}
//			result.addAll(charPositions);
//		}
//		return result;
//	}
//
//	private static List<PdfPageContentPositions> getPdfContentPostionsList(byte[] pdfData) throws IOException {
//		PdfReader reader = new PdfReader(pdfData);
//
//		List<PdfPageContentPositions> result = new ArrayList<PdfPageContentPositions>();
//
//		int pages = reader.getNumberOfPages();
//		for (int pageNum = 1; pageNum <= pages; pageNum++) {
//			float width = reader.getPageSize(pageNum).getWidth();
//			float height = reader.getPageSize(pageNum).getHeight();
//
//			PdfRenderListener pdfRenderListener = new PdfRenderListener(pageNum, width, height);
//
//			// 解析pdf，定位位置
//			PdfContentStreamProcessor processor = new PdfContentStreamProcessor(pdfRenderListener);
//			PdfDictionary pageDic = reader.getPageN(pageNum);
//			PdfDictionary resourcesDic = pageDic.getAsDict(PdfName.RESOURCES);
//			try {
//				processor.processContent(ContentByteUtils.getContentBytesForPage(reader, pageNum), resourcesDic);
//			} catch (IOException e) {
//				reader.close();
//				throw e;
//			}
//
//			String content = pdfRenderListener.getContent();
//			List<CharPosition> charPositions = pdfRenderListener.getcharPositions();
//
//			List<float[]> positionsList = new ArrayList<float[]>();
//			for (CharPosition charPosition : charPositions) {
//				float[] positions = new float[] { charPosition.getPageNum(), charPosition.getX(), charPosition.getY() };
//				positionsList.add(positions);
//			}
//
//			PdfPageContentPositions pdfPageContentPositions = new PdfPageContentPositions();
//			pdfPageContentPositions.setContent(content);
//			pdfPageContentPositions.setPostions(positionsList);
//
//			result.add(pdfPageContentPositions);
//		}
//		reader.close();
//		return result;
//	}
//
//	private static List<float[]> findPositions(String keyword, PdfPageContentPositions pdfPageContentPositions) {
//
//		List<float[]> result = new ArrayList<float[]>();
//
//		String content = pdfPageContentPositions.getContent();
//		List<float[]> charPositions = pdfPageContentPositions.getPositions();
//
//		for (int pos = 0; pos < content.length();) {
//			int positionIndex = content.indexOf(keyword, pos);
//			if (positionIndex == -1) {
//				break;
//			}
//			float[] postions = charPositions.get(positionIndex);
//			result.add(postions);
//			pos = positionIndex + 1;
//		}
//		return result;
//	}
//
//	private static class PdfPageContentPositions {
//		private String content;
//		private List<float[]> positions;
//
//		public String getContent() {
//			return content;
//		}
//
//		public void setContent(String content) {
//			this.content = content;
//		}
//
//		public List<float[]> getPositions() {
//			return positions;
//		}
//
//		public void setPostions(List<float[]> positions) {
//			this.positions = positions;
//		}
//	}
//
//	private static class PdfRenderListener implements RenderListener {
//		private int pageNum;
//		private float pageWidth;
//		private float pageHeight;
//		private StringBuilder contentBuilder = new StringBuilder();
//		private List<CharPosition> charPositions = new ArrayList<CharPosition>();
//
//		public PdfRenderListener(int pageNum, float pageWidth, float pageHeight) {
//			this.pageNum = pageNum;
//			this.pageWidth = pageWidth;
//			this.pageHeight = pageHeight;
//		}
//
//		@Override
//		public void beginTextBlock() {
//
//		}
//
//		@Override
//		public void renderText(TextRenderInfo renderInfo) {
//			List<TextRenderInfo> characterRenderInfos = renderInfo.getCharacterRenderInfos();
//			for (TextRenderInfo textRenderInfo : characterRenderInfos) {
//				String word = textRenderInfo.getText();
//				if (word.length() > 1) {
//					word = word.substring(word.length() - 1, word.length());
//				}
//				com.itextpdf.awt.geom.Rectangle2D.Float rectangle = textRenderInfo.getAscentLine()
//						.getBoundingRectange();
//				double x = rectangle.getMinX();
//				double y = rectangle.getMaxY();
//
//				float xPercent = Math.round(x / pageWidth * 10000) / 10000f;
//				float yPercent = Math.round((1 - y / pageHeight) * 10000) / 10000f;//
//
//				CharPosition charPosition = new CharPosition(pageNum, xPercent, yPercent);
//				charPositions.add(charPosition);
//				contentBuilder.append(word);
//			}
//		}
//
//		@Override
//		public void endTextBlock() {
//
//		}
//
//		@Override
//		public void renderImage(ImageRenderInfo renderInfo) {
//
//		}
//
//		public String getContent() {
//			return contentBuilder.toString();
//		}
//
//		public List<CharPosition> getcharPositions() {
//			return charPositions;
//		}
//	}
//
//	private static class CharPosition {
//		private int pageNum = 0;
//		private float x = 0;
//		private float y = 0;
//
//		public CharPosition(int pageNum, float x, float y) {
//			this.pageNum = pageNum;
//			this.x = x;
//			this.y = y;
//		}
//
//		public int getPageNum() {
//			return pageNum;
//		}
//
//		public float getX() {
//			return x;
//		}
//
//		public float getY() {
//			return y;
//		}
//
//		@Override
//		public String toString() {
//			return "[pageNum=" + this.pageNum + ",x=" + this.x + ",y=" + this.y + "]";
//		}
//	}
}